package com.example.mybatisplusdemo.service;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.example.mybatisplusdemo.mapper.AirportMapper;
import com.example.mybatisplusdemo.mapper.FlightMapper;
import com.example.mybatisplusdemo.model.domain.Airport;
import com.example.mybatisplusdemo.model.domain.Flight;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 目的地推荐服务类
 * </p>
 *
 * @author yangpengfei
 * @since 2025/01/20
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class DestinationRecommendationService {

    private final AirportMapper airportMapper;
    private final FlightMapper flightMapper;

    // 价格区间常量
    private static final BigDecimal CHEAP_THRESHOLD = new BigDecimal("3000");
    private static final BigDecimal MEDIUM_THRESHOLD = new BigDecimal("6000");
    
    // 兴趣标签映射
    private static final Map<String, List<String>> INTEREST_COUNTRY_MAP = new HashMap<>();
    
    static {
        INTEREST_COUNTRY_MAP.put("海滩度假", Arrays.asList("泰国", "印度尼西亚", "马来西亚", "菲律宾"));
        INTEREST_COUNTRY_MAP.put("历史文化", Arrays.asList("日本", "韩国", "中国", "意大利", "法国", "英国"));
        INTEREST_COUNTRY_MAP.put("城市购物", Arrays.asList("日本", "韩国", "新加坡", "香港", "法国", "英国"));
    }

    /**
     * 获取热门目的地推荐
     * 
     * 业务逻辑说明：
     * 1. 查询所有航班数据
     * 2. 按目的地分组统计航班数量和平均价格
     * 3. 根据航班频次排序确定热门程度
     * 4. 结合机场信息返回完整的目的地数据
     * 
     * @param departure 出发地机场代码，可选参数
     * @param limit 返回结果数量限制
     * @return List<Map<String, Object>> 热门目的地列表
     */
    public List<Map<String, Object>> getPopularDestinations(String departure, Integer limit) {
        QueryWrapper<Flight> flightQuery = new QueryWrapper<>();
        
        if (departure != null && !departure.isEmpty()) {
            flightQuery.eq("departure_airport_code", departure);
        }
        
        // 查询所有航班
        List<Flight> flights = flightMapper.selectList(flightQuery);
        
        // 按目的地分组统计
        Map<String, List<Flight>> flightsByDestination = flights.stream()
                .collect(Collectors.groupingBy(Flight::getArrivalAirportCode));
        
        List<Map<String, Object>> destinations = new ArrayList<>();
        
        for (Map.Entry<String, List<Flight>> entry : flightsByDestination.entrySet()) {
            String destinationCode = entry.getKey();
            List<Flight> destinationFlights = entry.getValue();
            
            // 获取机场信息
            Airport airport = airportMapper.selectById(destinationCode);
            if (airport == null) continue;
            
            // 计算统计数据
            double avgPrice = destinationFlights.stream()
                    .mapToDouble(f -> f.getPrice().doubleValue())
                    .average().orElse(0.0);
            
            int flightCount = destinationFlights.size();
            
            // 确定价格等级
            String priceLevel = getPriceLevel(BigDecimal.valueOf(avgPrice));
            
            Map<String, Object> destination = new HashMap<>();
            destination.put("name", airport.getCity());
            destination.put("country", airport.getCountry());
            destination.put("airportCode", destinationCode);
            destination.put("airportName", airport.getName());
            destination.put("price", Math.round(avgPrice));
            destination.put("priceLevel", priceLevel);
            destination.put("flightCount", flightCount);
            destination.put("popularityLevel", getPopularityLevel(flightCount));
            
            destinations.add(destination);
        }
        
        // 按航班数量排序（热门程度）
        destinations.sort((a, b) -> Integer.compare(
                (Integer) b.get("flightCount"), 
                (Integer) a.get("flightCount")
        ));
        
        return destinations.stream().limit(limit).collect(Collectors.toList());
    }

    /**
     * 获取个性化目的地推荐
     * 
     * 业务逻辑说明：
     * 1. 根据出发地查询可达目的地
     * 2. 按预算范围过滤航班
     * 3. 根据兴趣标签匹配目的地
     * 4. 计算匹配度评分
     * 
     * @param departure 出发地机场代码
     * @param minBudget 最小预算
     * @param maxBudget 最大预算
     * @param duration 出行天数
     * @param interests 兴趣标签
     * @return List<Map<String, Object>> 个性化推荐列表
     */
    public List<Map<String, Object>> getPersonalizedRecommendations(
            String departure, Integer minBudget, Integer maxBudget, Integer duration, String interests) {
        
        QueryWrapper<Flight> flightQuery = new QueryWrapper<>();
        flightQuery.eq("departure_airport_code", departure)
                .between("price", minBudget, maxBudget);
        
        List<Flight> flights = flightMapper.selectList(flightQuery);
        
        // 按目的地分组
        Map<String, List<Flight>> flightsByDestination = flights.stream()
                .collect(Collectors.groupingBy(Flight::getArrivalAirportCode));
        
        List<String> interestList = interests != null ? 
                Arrays.asList(interests.split(",")) : new ArrayList<>();
        
        List<Map<String, Object>> recommendations = new ArrayList<>();
        
        for (Map.Entry<String, List<Flight>> entry : flightsByDestination.entrySet()) {
            String destinationCode = entry.getKey();
            List<Flight> destinationFlights = entry.getValue();
            
            Airport airport = airportMapper.selectById(destinationCode);
            if (airport == null) continue;
            
            // 计算平均价格和飞行时间
            double avgPrice = destinationFlights.stream()
                    .mapToDouble(f -> f.getPrice().doubleValue())
                    .average().orElse(0.0);
            
            double avgFlightTime = destinationFlights.stream()
                    .mapToDouble(f -> f.getDuration() / 60.0) // 转换为小时
                    .average().orElse(0.0);
            
            // 计算匹配度评分
            Map<String, Integer> matchScore = calculateMatchScore(
                    airport.getCountry(), interestList, avgPrice, minBudget, maxBudget);
            
            // 生成推荐理由
            String reason = generateRecommendationReason(
                    airport.getCity(), airport.getCountry(), interestList, duration, avgPrice);
            
            Map<String, Object> recommendation = new HashMap<>();
            recommendation.put("destination", airport.getCity());
            recommendation.put("country", airport.getCountry());
            recommendation.put("airportCode", destinationCode);
            recommendation.put("flightTime", Math.round(avgFlightTime * 10) / 10.0);
            recommendation.put("budgetRange", Math.round(avgPrice * 0.8) + "-" + Math.round(avgPrice * 1.2));
            recommendation.put("popularityLevel", getPopularityLevel(destinationFlights.size()));
            recommendation.put("reason", reason);
            recommendation.put("matchScore", matchScore);
            
            recommendations.add(recommendation);
        }
        
        // 按匹配度排序
        recommendations.sort((a, b) -> {
            Map<String, Integer> scoreA = (Map<String, Integer>) a.get("matchScore");
            Map<String, Integer> scoreB = (Map<String, Integer>) b.get("matchScore");
            int totalA = scoreA.get("interests") + scoreA.get("budget");
            int totalB = scoreB.get("interests") + scoreB.get("budget");
            return Integer.compare(totalB, totalA);
        });
        
        return recommendations.stream().limit(10).collect(Collectors.toList());
    }

    /**
     * 获取目的地详细信息
     * 
     * @param destinationCode 目的地机场代码
     * @param departure 出发地机场代码
     * @return Map<String, Object> 目的地详细信息
     */
    public Map<String, Object> getDestinationDetail(String destinationCode, String departure) {
        Airport airport = airportMapper.selectById(destinationCode);
        if (airport == null) {
            throw new RuntimeException("目的地不存在: " + destinationCode);
        }
        
        Map<String, Object> detail = new HashMap<>();
        detail.put("name", airport.getCity());
        detail.put("country", airport.getCountry());
        detail.put("airportCode", destinationCode);
        detail.put("airportName", airport.getName());
        detail.put("timezone", airport.getTimezone());
        
        // 如果提供了出发地，查询航班信息
        if (departure != null && !departure.isEmpty()) {
            QueryWrapper<Flight> flightQuery = new QueryWrapper<>();
            flightQuery.eq("departure_airport_code", departure)
                    .eq("arrival_airport_code", destinationCode);
            
            List<Flight> flights = flightMapper.selectList(flightQuery);
            
            if (!flights.isEmpty()) {
                double avgPrice = flights.stream()
                        .mapToDouble(f -> f.getPrice().doubleValue())
                        .average().orElse(0.0);
                
                detail.put("avgPrice", Math.round(avgPrice));
                detail.put("flightCount", flights.size());
                detail.put("priceLevel", getPriceLevel(BigDecimal.valueOf(avgPrice)));
            }
        }
        
        return detail;
    }

    /**
     * 获取价格地图数据
     * 
     * @param departure 出发地机场代码
     * @return Map<String, Object> 价格地图数据
     */
    public Map<String, Object> getPriceMapData(String departure) {
        QueryWrapper<Flight> flightQuery = new QueryWrapper<>();
        flightQuery.eq("departure_airport_code", departure);
        
        List<Flight> flights = flightMapper.selectList(flightQuery);
        
        Map<String, List<Flight>> flightsByDestination = flights.stream()
                .collect(Collectors.groupingBy(Flight::getArrivalAirportCode));
        
        List<Map<String, Object>> asiaDestinations = new ArrayList<>();
        List<Map<String, Object>> europeDestinations = new ArrayList<>();
        
        for (Map.Entry<String, List<Flight>> entry : flightsByDestination.entrySet()) {
            String destinationCode = entry.getKey();
            List<Flight> destinationFlights = entry.getValue();
            
            Airport airport = airportMapper.selectById(destinationCode);
            if (airport == null) continue;
            
            double avgPrice = destinationFlights.stream()
                    .mapToDouble(f -> f.getPrice().doubleValue())
                    .average().orElse(0.0);
            
            Map<String, Object> destination = new HashMap<>();
            destination.put("name", airport.getCity());
            destination.put("country", airport.getCountry());
            destination.put("price", Math.round(avgPrice));
            destination.put("priceLevel", getPriceLevel(BigDecimal.valueOf(avgPrice)));
            destination.put("position", generateRandomPosition(airport.getCountry()));
            
            // 简单的地区分类逻辑
            if (isAsianCountry(airport.getCountry())) {
                asiaDestinations.add(destination);
            } else if (isEuropeanCountry(airport.getCountry())) {
                europeDestinations.add(destination);
            }
        }
        
        Map<String, Object> result = new HashMap<>();
        result.put("asiaDestinations", asiaDestinations);
        result.put("europeDestinations", europeDestinations);
        
        return result;
    }

    // 私有辅助方法
    
    /**
     * 根据价格确定价格等级
     */
    private String getPriceLevel(BigDecimal price) {
        if (price.compareTo(CHEAP_THRESHOLD) <= 0) {
            return "cheap";
        } else if (price.compareTo(MEDIUM_THRESHOLD) <= 0) {
            return "medium";
        } else {
            return "expensive";
        }
    }
    
    /**
     * 根据航班数量确定热门程度
     */
    private String getPopularityLevel(int flightCount) {
        if (flightCount >= 20) {
            return "非常高";
        } else if (flightCount >= 10) {
            return "高";
        } else if (flightCount >= 5) {
            return "中";
        } else {
            return "低";
        }
    }
    
    /**
     * 计算匹配度评分
     */
    private Map<String, Integer> calculateMatchScore(
            String country, List<String> interests, double avgPrice, int minBudget, int maxBudget) {
        
        // 兴趣匹配度评分
        int interestScore = 60; // 基础分
        for (String interest : interests) {
            List<String> matchingCountries = INTEREST_COUNTRY_MAP.get(interest);
            if (matchingCountries != null && matchingCountries.contains(country)) {
                interestScore += 15;
            }
        }
        interestScore = Math.min(interestScore, 100);
        
        // 预算匹配度评分
        int budgetScore;
        double budgetRange = maxBudget - minBudget;
        double pricePosition = (avgPrice - minBudget) / budgetRange;
        
        if (pricePosition >= 0.3 && pricePosition <= 0.7) {
            budgetScore = 90; // 价格在预算中间区间
        } else if (pricePosition >= 0.1 && pricePosition <= 0.9) {
            budgetScore = 75; // 价格在预算合理区间
        } else {
            budgetScore = 60; // 价格在预算边缘
        }
        
        Map<String, Integer> matchScore = new HashMap<>();
        matchScore.put("interests", interestScore);
        matchScore.put("budget", budgetScore);
        
        return matchScore;
    }
    
    /**
     * 生成推荐理由
     */
    private String generateRecommendationReason(
            String city, String country, List<String> interests, int duration, double avgPrice) {
        
        StringBuilder reason = new StringBuilder();
        reason.append(city).append("是一个");
        
        // 根据兴趣添加描述
        if (interests.contains("海滩度假")) {
            reason.append("拥有美丽海滩的度假胜地，");
        } else if (interests.contains("历史文化")) {
            reason.append("历史文化底蕴深厚的城市，");
        } else if (interests.contains("城市购物")) {
            reason.append("购物天堂和现代化都市，");
        } else {
            reason.append("充满魅力的旅游目的地，");
        }
        
        // 根据天数添加描述
        if (duration <= 3) {
            reason.append("适合短期周末游，");
        } else if (duration <= 7) {
            reason.append("适合一周左右的深度游，");
        } else {
            reason.append("适合长期度假，");
        }
        
        // 根据价格添加描述
        if (avgPrice <= 3000) {
            reason.append("价格经济实惠，性价比很高");
        } else if (avgPrice <= 6000) {
            reason.append("价格适中，体验丰富");
        } else {
            reason.append("虽然价格较高，但体验绝对值得");
        }
        
        return reason.toString();
    }
    
    /**
     * 判断是否为亚洲国家
     */
    private boolean isAsianCountry(String country) {
        List<String> asianCountries = Arrays.asList(
                "中国", "日本", "韩国", "泰国", "新加坡", "马来西亚", 
                "印度尼西亚", "菲律宾", "越南", "印度", "香港", "台湾"
        );
        return asianCountries.contains(country);
    }
    
    /**
     * 判断是否为欧洲国家
     */
    private boolean isEuropeanCountry(String country) {
        List<String> europeanCountries = Arrays.asList(
                "法国", "英国", "德国", "意大利", "西班牙", "荷兰", 
                "瑞士", "奥地利", "比利时", "瑞典", "挪威", "丹麦"
        );
        return europeanCountries.contains(country);
    }
    
    /**
     * 根据国家生成随机位置坐标（用于地图显示）
     */
    private Map<String, Double> generateRandomPosition(String country) {
        Map<String, Double> position = new HashMap<>();
        
        // 简化的地理位置映射
        if (isAsianCountry(country)) {
            position.put("x", 70.0 + Math.random() * 20); // 亚洲区域 x: 70-90
            position.put("y", 20.0 + Math.random() * 40); // y: 20-60
        } else if (isEuropeanCountry(country)) {
            position.put("x", 40.0 + Math.random() * 20); // 欧洲区域 x: 40-60
            position.put("y", 15.0 + Math.random() * 25); // y: 15-40
        } else {
            // 其他地区随机位置
            position.put("x", Math.random() * 100);
            position.put("y", Math.random() * 80);
        }
        
        return position;
    }
}